#include "ui.h"

Layout UI::computeLayout(HWND hWnd, const Engine& eng) const {
    RECT r; GetClientRect(hWnd, &r);
    Layout ly{};
    ly.panelRect = r; ly.panelRect.left = r.right - cfg.panelWidth;
    ly.gridRect = r; ly.gridRect.right = r.right - cfg.panelWidth;
    int gw = ly.gridRect.right - ly.gridRect.left - cfg.margin*2;
    int gh = ly.gridRect.bottom - ly.gridRect.top - cfg.margin*2;
    const Grid& g = const_cast<Engine&>(eng).getGrid();
    ly.cellW = gw / g.cols;
    ly.cellH = gh / g.rows;
    return ly;
}

static void fillRect(HDC hdc, const RECT& r, COLORREF color) {
    HBRUSH b = CreateSolidBrush(color);
    FillRect(hdc, const_cast<RECT*>(&r), b);
    DeleteObject(b);
}

void UI::draw(HWND hWnd, HDC hdc, const Engine& eng) const {
    Layout ly = computeLayout(hWnd, eng);
    const Grid& g = const_cast<Engine&>(eng).getGrid();
    RECT bg = ly.gridRect;
    fillRect(hdc, bg, RGB(245,245,245));
    for (int r = 0; r < g.rows; ++r) {
        for (int c = 0; c < g.cols; ++c) {
            RECT cell{ ly.gridRect.left + cfg.margin + c*ly.cellW,
                       ly.gridRect.top + cfg.margin + r*ly.cellH,
                       ly.gridRect.left + cfg.margin + (c+1)*ly.cellW - 1,
                       ly.gridRect.top + cfg.margin + (r+1)*ly.cellH - 1 };
            COLORREF color = RGB(230,230,230);
            Pos p{r,c};
            long long k = (long long)r * g.cols + c;
            if (g.is_blocked(p)) color = RGB(0,0,0);
            if (eng.getAlgoState().visited.count(k)) color = RGB(102,178,255);
            if (eng.getAlgoState().frontier.count(k)) color = RGB(255,165,0);
            fillRect(hdc, cell, color);
            if (g.start.r==r && g.start.c==c) fillRect(hdc, cell, RGB(0,200,0));
            if (g.goal.r==r && g.goal.c==c) fillRect(hdc, cell, RGB(200,0,0));
        }
    }
    for (auto p : eng.getAlgoState().path) {
        RECT cell{ ly.gridRect.left + cfg.margin + p.c*ly.cellW,
                   ly.gridRect.top + cfg.margin + p.r*ly.cellH,
                   ly.gridRect.left + cfg.margin + (p.c+1)*ly.cellW - 1,
                   ly.gridRect.top + cfg.margin + (p.r+1)*ly.cellH - 1 };
        fillRect(hdc, cell, RGB(128,0,128));
    }

    RECT panel = ly.panelRect;
    fillRect(hdc, panel, RGB(255,255,255));
    HFONT font = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    SelectObject(hdc, font);
    SetBkMode(hdc, TRANSPARENT);
    wchar_t buf[256];
    auto stats = eng.getStats();
    const char* an = eng.algoName();
    wsprintfW(buf, L"Algorithm: %S\nSteps: %d\nVisited: %d\nPath: %d\n\n[1-6] 算法切换\n[Space] 开始/暂停\n[N] 单步\n[R] 重置\n[C] 清空障碍\n[M] 随机地图\n[D] 对角开关\n[S/G] 设置起点/终点", an, stats.steps, stats.visited, stats.path_len);
    RECT tr = panel; tr.left += 10; tr.top += 10;
    DrawTextW(hdc, buf, -1, &tr, DT_LEFT|DT_TOP);
    wchar_t footer[128];
    wsprintfW(footer, L"Find Road UI - Zengtudor");
    RECT fr = panel; fr.left += 10; fr.bottom -= 10;
    DrawTextW(hdc, footer, -1, &fr, DT_LEFT|DT_BOTTOM);
}

bool UI::pointToCell(const Layout& ly, POINT pt, const Engine& eng, Pos& out) const {
    if (pt.x < ly.gridRect.left + cfg.margin || pt.x >= ly.gridRect.right - cfg.margin) return false;
    if (pt.y < ly.gridRect.top + cfg.margin || pt.y >= ly.gridRect.bottom - cfg.margin) return false;
    const Grid& g = const_cast<Engine&>(eng).getGrid();
    int gx = pt.x - (ly.gridRect.left + cfg.margin);
    int gy = pt.y - (ly.gridRect.top + cfg.margin);
    int c = gx / ly.cellW;
    int r = gy / ly.cellH;
    if (r<0||c<0||r>=g.rows||c>=g.cols) return false;
    out = Pos{r,c};
    return true;
}

